#include "QIrrAttributesProxy.h"
#include "QColorProperty.h"
#include "QFileProperty.h"
#include "QVector3DProperty.h"
#include "QEnumProperty.h"
#include "QEmptyProperty.h"
#include "QBoolProperty.h"
#include "QNumberProperty.h"
#include "QPropertySet.h"

using namespace QPE;

QIrrAttributesProxy::QIrrAttributesProxy(QObject *parent)
	: QPropertyModel(parent), Attributes(NULL)
{
	connect(this, SIGNAL(onDataChangedByEditor(QProperty*)), this, SLOT(onAttributeChangedByEditor(QProperty*)));
}

QIrrAttributesProxy::~QIrrAttributesProxy()
{
	if(Attributes)
		Attributes->drop();
	Attributes = NULL;
}


void QIrrAttributesProxy::setAttributes(irr::io::IAttributes* attributes)
{
	if(Attributes == attributes)
		return;

	if(Attributes)
		Attributes->drop();

	Attributes = attributes;

	if(Attributes)
		Attributes->grab();

	updateAllProperties();
}

void QIrrAttributesProxy::updateAllProperties()
{
	QPropertyModel::clear();

	if(Attributes != NULL)
	{
		int tmpAttrCount = Attributes->getAttributeCount();
		for (int i = 0; i < tmpAttrCount; ++i)
		{
			irr::io::E_ATTRIBUTE_TYPE propType = Attributes->getAttributeType(i);
			irr::core::stringc propName = Attributes->getAttributeName(i);

			switch(propType)
			{
				case irr::io::EAT_INT:
					{
						QIntegerProperty* tmpProp = new QIntegerProperty(propName.c_str());
						tmpProp->setValue(QVariant(Attributes->getAttributeAsInt(i)));
						addProperty(tmpProp, propName.c_str());
					}
					break;
				case irr::io::EAT_STRING:
					createProperty(propName.c_str(), propName.c_str(), "", QVariant(Attributes->getAttributeAsString(i).c_str()));
					break;
				case irr::io::EAT_BOOL:
					{
						QBoolProperty* tmpProp = new QBoolProperty(propName.c_str());
						tmpProp->setValue(QVariant(Attributes->getAttributeAsInt(i)));
						addProperty(tmpProp, propName.c_str());
					}
					break;
				case irr::io::EAT_FLOAT:
					{
						QDoubleProperty* tmpProp = new QDoubleProperty(propName.c_str());
						tmpProp->setValue(QVariant(Attributes->getAttributeAsInt(i)));
						addProperty(tmpProp, propName.c_str());
					}
					break;
				case irr::io::EAT_COLOR:
					{
						irr::video::SColor tmpColor = Attributes->getAttributeAsColor(i);
						QColorProperty* tmpColorProp = new QColorProperty(propName.c_str());
						tmpColorProp->setValue(QColor(tmpColor.getRed(), tmpColor.getGreen(), tmpColor.getBlue(), tmpColor.getAlpha()));
						addProperty(tmpColorProp, propName.c_str());
					}
					break;
				case irr::io::EAT_COLORF:
					{
						irr::video::SColorf tmpColorf = Attributes->getAttributeAsColorf(i);
						int tmp_red = int(tmpColorf.r * 255.0f);
						int tmp_green = int(tmpColorf.g * 255.0f);
						int tmp_blue = int(tmpColorf.b * 255.0f);
						int tmp_alpha = int(tmpColorf.a * 255.0f);
						QColorProperty* tmpColorProp = new QColorProperty(propName.c_str());
						tmpColorProp->setValue(QColor(tmp_red, tmp_green, tmp_blue, tmp_alpha));
						addProperty(tmpColorProp, propName.c_str());
					}
					break;
				case irr::io::EAT_VECTOR3D:
					{
						irr::core::vector3df tmpVect = Attributes->getAttributeAsVector3d(i);
						QVector3DProperty* tmpProp = new QVector3DProperty(propName.c_str());
						tmpProp->setVector(tmpVect.X, tmpVect.Y, tmpVect.Z);
						addProperty(tmpProp, propName.c_str());
					}
					break;
				case irr::io::EAT_ENUM:
					{
						QEnumProperty* tmpProp = new QEnumProperty(propName.c_str());

						irr::core::array<irr::core::stringc> tmpIrrLiterals;
						Attributes->getAttributeEnumerationLiteralsOfEnumeration(i, tmpIrrLiterals);

						QStringList tmpQLiterals;
						int tmpCurrentIndex = -1;
						irr::core::stringc tmpCurrentLiteral = Attributes->getAttributeAsEnumeration(i);
						for(int j = 0; j < tmpIrrLiterals.size(); ++j)
						{
							tmpQLiterals.append(tmpIrrLiterals[j].c_str());
							if(tmpCurrentIndex < 0 && tmpCurrentLiteral == tmpIrrLiterals[j])
								tmpCurrentIndex = j;
						}

						tmpProp->setLiterals(tmpQLiterals);

						if(tmpCurrentIndex > 0 && tmpCurrentIndex < tmpIrrLiterals.size())
							tmpProp->setValue(tmpCurrentIndex);

						addProperty(tmpProp, propName.c_str());
					}
					break;
				case irr::io::EAT_TEXTURE:
					{
						QFileProperty* tmpProp = new QFileProperty(propName.c_str());
						tmpProp->setFileFilters(tr("Texture Files (*.png *.jpg *.bmp *.jpeg *.tif *.tga)"));
						tmpProp->setFile(Attributes->getAttributeAsString(i).c_str());
						addProperty(tmpProp, propName.c_str());
					}
					break;
			default:
				break;
			}
		}
	}
}

void QIrrAttributesProxy::clear()
{
	setAttributes(NULL);
}

void QIrrAttributesProxy::onAttributeChanged(const irr::core::stringc& name)
{
	if(!Attributes)
		return;

	irr::io::E_ATTRIBUTE_TYPE propType = Attributes->getAttributeType(name.c_str());
	QProperty* currentProperty = getProperty(name.c_str());
	if(!currentProperty)
		return;

	switch(propType)
	{
		case irr::io::EAT_INT:
			currentProperty->setValue(QVariant(Attributes->getAttributeAsInt(name.c_str())));
			break;
		case irr::io::EAT_STRING:
			currentProperty->setValue(QVariant(Attributes->getAttributeAsString(name.c_str()).c_str()));
			break;
		case irr::io::EAT_BOOL:
			currentProperty->setValue(QVariant(Attributes->getAttributeAsBool(name.c_str())));
			break;
		case irr::io::EAT_FLOAT:
			currentProperty->setValue(QVariant(Attributes->getAttributeAsFloat(name.c_str())));
			break;
		case irr::io::EAT_COLOR:
			{
				irr::video::SColor tmpColor = Attributes->getAttributeAsColor(name.c_str());
				currentProperty->setValue(QColor(tmpColor.getRed(), tmpColor.getGreen(), tmpColor.getBlue(), tmpColor.getAlpha()));
			}
			break;
		case irr::io::EAT_COLORF:
			{
				irr::video::SColorf tmpColorf = Attributes->getAttributeAsColorf(name.c_str());
				int tmp_red = int(tmpColorf.r * 255.0f);
				int tmp_green = int(tmpColorf.g * 255.0f);
				int tmp_blue = int(tmpColorf.b * 255.0f);
				int tmp_alpha = int(tmpColorf.a * 255.0f);
				currentProperty->setValue(QColor(tmp_red, tmp_green, tmp_blue, tmp_alpha));
			}
			break;
		case irr::io::EAT_VECTOR3D:
			{
				irr::core::vector3df tmpVect = Attributes->getAttributeAsVector3d(name.c_str());
				QVector3DProperty* currentVectorProp = static_cast<QVector3DProperty*>(currentProperty);
				currentVectorProp->setVector(tmpVect.X, tmpVect.Y, tmpVect.Z);
			}
			break;
		case irr::io::EAT_ENUM:
			{
				currentProperty->setValue(QVariant(Attributes->getAttributeAsInt(name.c_str())));
			}
			break;
		case irr::io::EAT_TEXTURE:
			{
				currentProperty->setValue(Attributes->getAttributeAsString(name.c_str()).c_str());
			}
			break;
	default:
		break;
	}

	onDataChangedByModel(currentProperty);
}

void QIrrAttributesProxy::onAttributeChangedByEditor(QProperty* property)
{
	irr::core::stringc propName = convertQStringToIrrString(getPropertySet()->getPropertiesMap().key(property, ""));
	if(propName.empty())
		property = property->getParent();

	propName = convertQStringToIrrString(getPropertySet()->getPropertiesMap().key(property, ""));
	if(propName.empty())
		return;

	irr::io::E_ATTRIBUTE_TYPE propType = Attributes->getAttributeType(propName.c_str());

	switch(propType)
	{
		case irr::io::EAT_INT:
			Attributes->setAttribute(propName.c_str(), property->getValue().value<int>());
			break;
		case irr::io::EAT_STRING:
			Attributes->setAttribute(propName.c_str(), convertQStringToIrrString(property->getValue().value<QString>()).c_str());
			break;
		case irr::io::EAT_BOOL:
			Attributes->setAttribute(propName.c_str(), property->getValue().value<bool>());
			break;
		case irr::io::EAT_FLOAT:
			Attributes->setAttribute(propName.c_str(), property->getValue().value<float>());
			break;
		case irr::io::EAT_COLOR:
			{
				QColor tmpColor = property->getValue().value<QColor>();
				Attributes->setAttribute(propName.c_str(), irr::video::SColor(tmpColor.alpha(), tmpColor.red(), tmpColor.red(), tmpColor.blue()));
			}
			break;
		case irr::io::EAT_COLORF:
			{
				QColor tmpColor = property->getValue().value<QColor>();
				Attributes->setAttribute(propName.c_str(), irr::video::SColorf(tmpColor.redF(), tmpColor.greenF(), tmpColor.blueF(), tmpColor.alphaF()));
			}
			break;
		case irr::io::EAT_VECTOR3D:
			{
				QVector3DProperty* currentVectorProp = static_cast<QVector3DProperty*>(property);
				Vector3D tmpVect = currentVectorProp->getVector();
				Attributes->setAttribute(propName.c_str(), irr::core::vector3df(tmpVect.X, tmpVect.Y, tmpVect.Z));
			}
			break;
		case irr::io::EAT_ENUM:
			{
				Attributes->setAttribute(propName.c_str(), property->getValue().value<int>());
			}
			break;
		case irr::io::EAT_TEXTURE:
			{
				Attributes->setAttribute(propName.c_str(), convertQStringToIrrString(property->getValue().value<QString>()).c_str());
			}
			break;
	default:
		break;
	}

	emit attributesChangedByEditor(Attributes);
}


irr::core::stringc QIrrAttributesProxy::convertQStringToIrrString(const QString& str)
{
	irr::core::stringc result;
	int strLength = str.size();

	for(int i = 0; i < strLength; ++i)
	{
		result.append(str.at(i).toAscii());
	}

	return result;
}

QString QIrrAttributesProxy::convertIrrStringToQString(const irr::core::stringc& str)
{
	QString result;
	int strLength = str.size();

	for(int i = 0; i < strLength; ++i)
	{
		result.append(str[i]);
	}

	return result;
}
